use anyhow::{Result, bail};
use std::collections::BTreeMap;

use crate::client::TongLianPayClient;
use crate::utils;

#[derive(Debug)]
pub struct RefundParams {
    // 退款金额，单位为分
    pub trxamt: i32,
    // 退款请求流水号，商户系统内部唯一
    pub reqsn: String,
    // 退款原交易流水号
    pub oldtrxid: String,
    // 退款备注
    pub remark: String,
    pub notify_url: String,
}
#[derive(Debug)]
pub struct RefundResponse {
    pub trxstatus: String,
    pub errmsg: Option<String>,
}
impl TongLianPayClient {
    pub async fn refund(&self, params: &RefundParams) -> Result<RefundResponse> {
        let mut body = BTreeMap::new();
        body.insert("cusid", self.mch_credential.cusid.as_str());
        body.insert("appid", self.mch_credential.appid.as_str());
        body.insert("signtype", self.mch_credential.signtype.as_str());

        let trxamt = format!("{}", params.trxamt);
        body.insert("trxamt", trxamt.as_str());

        body.insert("reqsn", params.reqsn.as_str());
        body.insert("oldtrxid", params.oldtrxid.as_str());

        let randomstr = utils::generate_none_str(32);
        body.insert("randomstr", randomstr.as_str());

        body.insert("remark", params.remark.as_str());
        body.insert("notify_url", params.notify_url.as_str());

        // 加签
        let plain = utils::btree_map_to_query_string(&body);
        let sign = self.mch_credential.sign(plain.as_str());
        body.insert("sign", &sign);

        let url = format!("{}/apiweb/tranx/refund", self.base_url);
        let response = self
            .client
            .post(&url)
            .form(&body)
            .header("Accept", "application/json")
            .send()
            .await?;
        if !response.status().is_success() {
            bail!("退款请求失败");
        }

        let mut response: BTreeMap<String, String> = response.json().await?;
        // check response has sign key
        if !response.contains_key("sign") {
            let msg = response
                .get("retmsg")
                .unwrap_or(&"退款下单失败".to_string())
                .to_string();

            bail!(msg);
        }

        // 验签
        self.mch_credential.verify_response(&mut response)?;

        // 处理返回结果
        let trxstatus = response
            .get("trxstatus")
            .cloned()
            .unwrap_or_else(|| "未知状态".to_string());
        let errmsg = response.get("errmsg").cloned();
        Ok(RefundResponse { trxstatus, errmsg })
    }
}
